<?php 
/*
Extension Name: Applicant Email Verification
Extension Url: http://getvanilla.com/
Description: Add a verification of the email to registration.
Version: 0.4.1
Author: Dinoboff
Author Url: dinoboff at hotmail dot com

Changelog:
  * Version 0.4.1
    * Fix a bug in the default role display on the registration page (Thanks to Alnokta for finding the bug)

  * Version 0.4.0:
  
    * Works only with vanilla 1.0.1 or higher. added a warning when the extension is enable on vanilla 1.0;
	* Use the new methode "SetDefinition()" to set the Dictionary entries. These entries won't overwrite the entries from the language packages or form conf/language.php;
	* You can add your own email template (email_Email_Verification.txt) to your language package or to the conf/ folder.
	  Applicant Email Verification will use in priority conf/email_Email_Verification.txt, languages/YOURLANGUAGE/email_Email_Verification.txt 
	  or extensions/ApplicantEmailVerification/conf/email_Email_Verification.txt.
*/

define('APPLICANT_EMAIL_VERIFICATION_PATH', dirname(__FILE__) . '/');

// check if you have the right version of vanilla for this add-on
if (!version_compare(APPLICATION_VERSION, '1.0.1', '>=')) {
	//Language definitions for vanilla 1.0
	$Context->Dictionary['EmailVerification_ErrVanillaVersion'] = 'Vanilla 1.0.1 or higher is required for the Applicant Email Verification';
	
	//display an error message on the extension page and registration page when the extension is used with Vanilla 1.0.0
	if ( $Context->SelfUrl == 'settings.php' && in_array(ForceIncomingString('PostBackAction', ''), array('Extensions', 'RegistrationChange')) ) 
	$Context->WarningCollector->Add($Context->GetDefinition('EmailVerification_ErrVanillaVersion'));
}
else {

	require(APPLICANT_EMAIL_VERIFICATION_PATH . 'library/EmailVerification.php');
	include(APPLICANT_EMAIL_VERIFICATION_PATH . 'conf/language.php');
	require(APPLICANT_EMAIL_VERIFICATION_PATH . 'conf/setting.php');
	
	
	if ( ($Context->SelfUrl == "people.php") && ($Context->Configuration['APPLICANT_EMAIL_VERIFICATION_ON']) ) {
	
		//Hack: no mail sent to admin after registration, but sent after activation. Only work with vanilla 1.0.1 and higher
		function EmailVerification_NoMailAdmin(&$UserManager) {
			$UserManager->Context->Configuration['ALLOW_IMMEDIATE_ACCESS'] = 1;
		}
		
		$Context->AddToDelegate('UserManager', 'PostRoleAssignment', 'EmailVerification_NoMailAdmin');
		
		function EmailVerification_SetBack_AllowImmediateAccess(&$ApplyForm) {
			$ApplyForm->Context->Configuration['ALLOW_IMMEDIATE_ACCESS'] = 0;
		}
		
		$Context->AddToDelegate('ApplyForm', 'PostCreateUser', 'EmailVerification_SetBack_AllowImmediateAccess');
		
		
		//set the message after application.
		if ($Context->Configuration['APPLICANT_EMAIL_VERIFICATION_APROVE']) $Context->Dictionary['ApplicationWillBeReviewed'] = $Context->Dictionary['EmailVerification_ForMembership'];
		else $Context->Dictionary['ApplicationWillBeReviewed'] = $Context->Dictionary['EmailVerification_ForApplicationReview'];
	
		//Assign a verification key to the new applicant
		function RegistrationViaEmailCreateKey(&$ApplyForm) {
			if ($ApplyForm->PostBackValidated && $ApplyForm->Applicant->UserID > 0) {
							
				$User = $ApplyForm->Applicant->UserID;
				$EmailVerification = $ApplyForm->Context->ObjectFactory->NewContextObject($ApplyForm->Context, "EmailVerification", $ApplyForm->Applicant);
				
				//Create the key and save it in the DB
				$EmailVerification->CreateKey();
				
				//send the email
				if ($ApplyForm->Context->WarningCollector->Count() == 0) {
					
					$Subject = $ApplyForm->Context->Configuration['APPLICATION_TITLE'].' '.$ApplyForm->Context->GetDefinition('EmailVerification');
					$File = 'email_Email_Verification.txt';
					$DefaultPath = APPLICANT_EMAIL_VERIFICATION_PATH . 'conf';
					$EmailVerification->MailKey($Subject, $File, $DefaultPath, 'people.php', 'ApplicantEmailVerification');
				}
			}
		}
		
		$Context->AddToDelegate('ApplyForm', 'PostCreateUser', 'RegistrationViaEmailCreateKey');
		
		
		//Check key and 
		//Create the new EmailVerification PostBackControl
		class ApplicantEmailVerification extends PostBackControl {
			var $User;
							
			
			function ApplicantEmailVerification (&$Context) {
				$this->Name = 'ApplicantEmailVerification';
				$this->ValidActions = array('ApplicantEmailVerification');
				$this->Constructor($Context);
				
				$this->PostBackValidated = 0;
				$VerificationKey = ForceIncomingString('k', '');
				$UserID = ForceIncomingInt('u', 0);
							
				if ($this->IsPostBack) {
					
					// Set up the page
					global $Banner, $Foot;
					$Banner->Properties['CssClass'] = 'Apply';
					$Foot->CssClass = 'Apply';
					$this->Context->PageTitle = $this->Context->GetDefinition('EmailVerification');
					
					
					$UserManager = $this->Context->ObjectFactory->NewContextObject($Context, 'UserManager');
					if ( !$this->User = $UserManager->GetUserById($UserID) ) $this->Context->WarningCollector->Add($this->Context->GetDefinition('EmailVerification_ErrNoUser'));
					
					if ($this->PostBackAction == 'ApplicantEmailVerification' && $this->Context->WarningCollector->Count() == 0) {
						
						//check the user is already a member of the forum
						if ( $this->User->RoleID > 1 ) $this->Context->WarningCollector->Add($Context->GetDefinition('EmailVerification_ErrAlreadyValidated'));
						else {
							//check if the user need has a Verification Key pending, and if the key in the database in the input is the same
							
							//Get the userkeyfrom the database					 
							$EmailVerification = $this->Context->ObjectFactory->NewContextObject($this->Context, "EmailVerification", $this->User);
							$EmailVerification->GetKey();
							
							//Check if the key exist
							if (!$EmailVerification->VerificationKey) $this->Context->WarningCollector->Add($this->Context->GetDefinition('EmailVerification_ErrNoKeyInDB'));
							
							//Check if the key from the DB and form the input are different
							if ( $EmailVerification->VerificationKey != $VerificationKey ) $this->Context->WarningCollector->Add($this->Context->GetDefinition('EmailVerification_ErrWrongKey'));
							else {
								//The are the same
								//so Change role
								$Urh = $this->Context->ObjectFactory->NewObject($this->Context, 'UserRoleHistory');
								$Urh->UserID = $this->User->UserID;
								$Urh->AdminUserID = 0;
								$Urh->RoleID = $this->Context->Configuration['APPLICANT_EMAIL_VERIFICATION_ROLE'];
								if ($this->Context->Configuration['APPLICANT_EMAIL_VERIFICATION_APROVE']) {
									$Urh->Notes = $this->Context->GetDefinition('RegistrationAccepted');
								} else {
									//or at least let the admin that still have to aprove the membership that the Email has been checked
									//*will have to find an other way to do it
									$Urh->Notes = $this->Context->GetDefinition('EmailVerificationPendingApproval');
								}
								if ($UserManager->AssignRole($Urh, 1)) $this->PostBackValidated = 1;
								
								//delete the Vefification key
								$EmailVerification->DeleteKey();
								
								//Let admins know a user is ready for approval
								if (!$this->Context->Configuration['APPLICANT_EMAIL_VERIFICATION_APROVE']) {
									$s = $this->Context->ObjectFactory->NewContextObject($this->Context, 'SqlBuilder');
									$s->SetMainTable('User', 'u');
									$s->AddJoin('Role', 'r', 'RoleID', 'u', 'RoleID', 'inner join');
									$s->AddWhere('r', 'PERMISSION_RECEIVE_APPLICATION_NOTIFICATION', '', 1, '=');
									$s->AddWhere('u', 'SendNewApplicantNotifications', '', 1, '=');
									$s->AddSelect(array('Name', 'Email'), 'u');
									$Administrators = $this->Context->Database->Select($s, $this->Name, 'ApplicantEmailVerification', 'An error occurred while retrieving administrator email addresses.', 0);
									// Fail silently if an error occurs while notifying administrators
								
									// Get the email body
									$File = $this->Context->Configuration['LANGUAGES_PATH']
										.$this->Context->Configuration['LANGUAGE']
										.'/email_applicant.txt';
									$EmailBody = @file_get_contents($File);
									
									if ($EmailBody && $Administrators) {
										$EmailBody = str_replace(
											array(
												"{applicant_name}",
												"{applicant_email}",
												"{application_url}"
											),
											array(
												$this->User->Name,
												$this->User->Email,
												ConcatenatePath(
													$this->Context->Configuration['BASE_URL'],
													GetUrl($this->Context->Configuration, 'account.php', '', 'u', $this->User->UserID)
												)
											),
											$EmailBody
										);
										
								
										if ($this->Context->Database->RowCount($Administrators) > 0) {
											$e = $this->Context->ObjectFactory->NewContextObject($this->Context, 'Email');
											$e->HtmlOn = 0;
											$e->ErrorManager = &$this->Context->ErrorManager;
											$e->WarningCollector = &$this->Context->WarningCollector;
											$e->AddFrom($this->User->Email, $this->User->Name);
											$AdminEmail = '';
											$AdminName = '';
											while ($Row = $this->Context->Database->GetRow($Administrators)) {
												$AdminEmail = ForceString($Row['Email'], '');
												$AdminName = ForceString($Row['Name'], '');
												if ($AdminEmail != '') $e->AddRecipient($AdminEmail, $AdminName);
											}
											$e->Subject = $this->Context->GetDefinition("NewApplicant");
											$e->Body = $EmailBody;						
											$e->Send(0);
										}
									}
								}
							} 
						}
					}
				}
			}
			
			function Render() {
				if($this->IsPostBack) {
					$this->CallDelegate('PreValidPostBackRender');
					echo '<div class="FormComplete">
					<h2>'.$this->Context->GetDefinition('EmailVerification').'</h2>';
					$this->Render_Warnings();
					if ($this->PostBackValidated) {
						echo '<ul>';
						if ($this->Context->Configuration['APPLICANT_EMAIL_VERIFICATION_APROVE']) {
							echo '<li>'.$this->Context->GetDefinition('EmailVerificationRegister').'</li>
							<li><a href="'.GetUrl($this->Context->Configuration, $this->Context->SelfUrl).'">'.$this->Context->GetDefinition('BackToSignInForm').'</a></li>';
						}
						else {
							echo '<li>'.$this->Context->GetDefinition('EmailVerificationDonePendingApproval').'</li>';
						}
						echo '</ul>';
					}
					echo '</div>';
					$this->CallDelegate('PostValidPostBackRender');
				}
			}
		}
		
		$ApplicantEmailVerification = $Context->ObjectFactory->NewContextObject($Context, 'ApplicantEmailVerification');
		$Page->AddRenderControl($ApplicantEmailVerification, $Configuration["CONTROL_POSITION_BODY_ITEM"]);
	}
	
	//Displayed the validation status of the applicant
	if ( ($Context->SelfUrl == "account.php") && ($Context->Configuration['APPLICANT_EMAIL_VERIFICATION_ON']) ) {	
	
		function AccountProfil_EmailVerificationSatus(&$Account) {
			if($Account->Context->Session->User->Permission("PERMISSION_CHANGE_USER_ROLE") && $Account->User->RoleID == 0) {
				$status = '';
				$EmailVerification = $Account->Context->ObjectFactory->NewContextObject($Account->Context, "EmailVerification", $Account->User);
				if ($EmailVerification->GetKey()) $status = $Account->Context->GetDefinition('EmailVerification_EmailNotValidated');
				else $status = $Account->Context->GetDefinition('EmailVerification_EmailValidated');
				echo '		<li>
				<h3>'.$Account->Context->GetDefinition('EmailVerification').'</h3>
				<p>'.$status.'</p>
			</li>';
			}
		}
		
		$Context->AddToDelegate('Account', 'PostBasicPropertiesRender', 'AccountProfil_EmailVerificationSatus');
		
	}
	
	
	
	//Add the option to turn verification ON in the Registration page setting
	function RegistrationForm_EmailVerification(&$RegistrationForm) {
		$ConstantManager = &$RegistrationForm->DelegateParameters['ConstantManager'];
		
		$Verification = ForceIncomingBool('APPLICANT_EMAIL_VERIFICATION_ON', 0);
		$ConstantManager->DefineSetting('APPLICANT_EMAIL_VERIFICATION_ON', $Verification);
		
		if ($Verification) {
			$ConstantManager->DefineSetting('APPLICANT_EMAIL_VERIFICATION_ROLE', $ConstantManager->_settings['DEFAULT_ROLE']);
			$ConstantManager->DefineSetting('DEFAULT_ROLE', 0);
			$ConstantManager->DefineSetting('APPLICANT_EMAIL_VERIFICATION_APROVE', $ConstantManager->_settings['ALLOW_IMMEDIATE_ACCESS']);
			$ConstantManager->DefineSetting('ALLOW_IMMEDIATE_ACCESS', 0);
		}
	}
	
	$Context->AddToDelegate('RegistrationForm', 'PreSaveSettings', 'RegistrationForm_EmailVerification');
	
	function RegistrationForm_PreRender_EmailVerification(&$RegistrationForm) {
		$RoleID = ForceIncomingString('RoleID', '');
		if ($RoleID == '') $RoleID = $RegistrationForm->Context->Configuration['APPLICANT_EMAIL_VERIFICATION_ROLE'];
		$RegistrationForm->RoleSelect->SelectedValue = $RoleID;	
	}
	
	$Context->AddToDelegate('RegistrationForm', 'PreRender', 'RegistrationForm_PreRender_EmailVerification');

		
	function RegistrationForm_Render_EmailVerification($RegistrationForm) {
		if ($RegistrationForm->PostBackAction == 'ProcessRegistrationChange') $checked = ForceIncomingBool('APPLICANT_EMAIL_VERIFICATION_ON', 0);
		else $checked = $RegistrationForm->Context->Configuration['APPLICANT_EMAIL_VERIFICATION_ON'];
		echo '							<li>
								<p><span>'.GetDynamicCheckBox('APPLICANT_EMAIL_VERIFICATION_ON', 1, $checked, '', $RegistrationForm->Context->GetDefinition('EmailVerificationOption')).'</span></p>
								<p class="Description">'.$RegistrationForm->Context->GetDefinition('EmailVerificationOptionNote').'</p>
							</li>';
	}
	
	$Context->AddToDelegate('RegistrationForm', 'PostRegistrationOptions', 'RegistrationForm_Render_EmailVerification');
	
}
?>